lpunbfandomcom-20200214-history
Seminário sobre Ada - 2012/2 - Grupo 1
'Linguagem Ada' Ada é a linguagem de programação que o resultado mais extensivo e dispendioso projeto de uma linguagem que já foi realizado até hoje. Desenvolvida pelo Departamento de Defesa americano na década de 70, Ada é uma linguagem de programação estrutura, de tipagem estática, imperativa, orientada a objetos e de alto nível, tendo origens no Pascal, Simula e outras linguagens. Ada possui compiladores validados para uso em áreas onde se precisa de alta confiabilidade e segurança. Histórico Em 1974, em um estudo de custo realizado foi determinado que o Departamento de Defesa americano gastava $3 bilhões anualmente em software, onde metade representava sistemas embarcados. Nesta época o Departamento de Defesa americano utilizava mais 450 linguagens de programação em seus projeto e nenhuma delas era padronizada, dessa forma o reuso era muito raro de acorrer. Logo as forças armadas americanas buscavam unificar suas linguagens de programação afim de construírem programas com possível reutilização de fragmentos de código, além de visarem uma linguagem robusta e segura, com performance alta, principalmente para uso em sistemas embarcados e de aplicações militares em tempo real, onde falhas sempre são críticas. Logo com intuito de solucionar estes problemas criaram o HOLWG (High Order Language Working Group), em 1975 criaram os requerimentos iniciais que a linguagem que eles buscavam e avaliaram 23 linguagens existentes na época em relação aos requerimentos. Em 1977 concluíram que nenhuma linguagem era adequada, porém Pascal, ALGOL 68 e PL/I eram consideradas um bom ponto de início para Departamento de Defesa americano queria. Durante o período de 1977 e 1983, a equipe liderada pelo francês Jean Ichbiah criou uma linguagem de programação, a qual havia sido encomendada pelo Departamento de Defesa americano, após várias revisões dos requisitos da linguagem. Essa linguagem conhecida somente como DoD-1 foi dada o nome de Ada em maio de 1979. Ada é uma linguagem estruturada, imperativa, de alto-nível orientada a objeto, possui checagem estática, estendida do Pascal, Simula e outras linguagens. Ada é bastante utilizada em áreas onde se precisa de sistemas que possuem alta confiabilidade e segurança, sendo utilizada em aviões comerciais e militares, controle de tráfego aéreo, sistemas ferroviários e instrumentos médicos. Com a incorporação de princípios modernos de engenharia de software, Ada é uma excelente linguagem para se usar desde de cursos básico a avançados de ciência da computação, e vem sendo um tópico interessante de estudo em várias universidades ao redor do mundo em especial na área de tecnologias em tempo real. O HOLWG foi dissolvido e substituído pelo AJPO (Ada Joint Program Office) em 12 de dezembro de 1980. Desde 1983, a linguagem passou por diversas revisões com correções e melhorias, abaixo a tabela com as inclusão das revisões. Em 1983 se tornou um padrão ANSI e sem mudanças em 1987 também se tornou um padrão ISO. O nome da linguagem foi uma homenagem a condessa de Lovelace, Ada Augusta Byron King (10 de Dezembro de 1815 – 27 de Novembro de 1852), que é conhecida por ser a primeira programadora do mundo, projetando algorítmos para a máquina analítica de Charles Babbage. Projeto de Linguagem Paradigma Ada é fortemente tipada, multi paradigmas, utilizando orientação a objetos e programação imperativa procedural. É uma linguagem de alto nível, porém assim como C e C++ não é de tão alto nível como outras linguagens. Ada oferece suporte a mesclagem de códigos de outras linguagens como C, Java, Perl, Python, Ruby, Fortran, Javascript, Pascal, Awk, Asm e outras, podendo compilar partes dos códigos, cada um com seu respectivo compilador e encapsulá-los em um único pacote. 'Usuários Característicos' Programadores de sistemas altamente especializados e treinados. Linguagem permite uma série de facilidades aos programadores, porém deixa a cargo do programador o gerenciamento de memória (quando são utilizados tipos de acesso). A liberação de variáveis instanciadas em tempo de execução pode ser feita em tempo de execução, utilizando o pacote Unchecked_Deallocation, ou ao será limpa ao final do programa, visto que a variável já tem um ponteiro de acesso. Caso um tipo de acesso deixe de referenciar um espaço de memória alocado em tempo de execução, este espaço continua sendo utilizado e não será limpo, ficando a cargo do sistema operacional reutilizar aquele endereço ou não. 'Domínio de Aplicação' Ada é utilizado em sistemas de controle, em veículos:sistemas de injeção automática, arrefeicimento, controle de tráfego; em sistemas de informação: transações bancárias, contabilização de caixa, sistemas de agamento, sistemas médicos embarcados em equipamentos (como de ressonância magnética), transmissão de dados com criptografia. O principal uso é de aplicações militares, americanas e canadenses, onde é utilizado em automóveis, mísseis, satélites, caças, submarinos e outros. Um dos principais usos gerais é no controle de tráfego aéreo, onde sua capacidade de programação concorrente entra em voga, e é utilizado pelos seguintes países: África do Sul, Alemanha, Austrália, Bélgica, Brasil, Canadá, China, Dinamarca, Escócia, Espanha, Estados Unidos, França, Grécia, Holanda, Hungria, Índia, Irlanda, Nova Zelândia, Reino Unido Singapura, Suécia e Taiwan. Critérios de Avaliação da Linguagem 'Performance' Ada tem uma pequena perda de performance quando comparada a implementações semelhantes em C e C++, porém continua superior ao Java. Todas as linguagens citadas são bastante utilizadas em sistemas embarcados, juntando ao fato de que Ada tem performance superior a de Java, não tem coletor de lixo, e por isso pode ser utilizada em sistemas de tempo real / crítico, ao fato de uma melhor manutebilidade que C++, é justo dizer que Ada se encontra em um meio termo bastante interessante entre Java e C++. Outro fato importante ao se considerar a perda de performance de Ada para C++, é o fato que Ada inclui diversos artifícios durante sua compilação, permitindo teste de cobertura, checagem de estouro de pilha de memória, checagem de estouro de índices entre outros, que eliminam problemas que podem acontecer em um programa C (memory leaks, referências cruzadas com ponteiros, e outros), sem perder a flexibilidade e robustez de algo que se assemelha a uma interseção entre C e Java. 'Manutebilidade' Ada foi projetada para reuso de código, e para melhorar tanto a quantidade de reuso, quanto na manutebilidade, foi focado a legibilidade do código, que por diversas vezes pode ser extenso, porém continua tendo boa legibilidade. A organização das estruturas como Classes e Pacotes, assim como em Java, facilitam a manutenção e gerenciamento das estruturas de um programa, além da visibilidade das classes e seus métodos, além dos pacotes. Toda procedure tem duas partes, que podem ser descritas como antes da palavra reservada begin da procedure e depois da palavra begin. procedure Main is --trecho para declaração de variáveis e tipos de acesso begin --inicio do segmento de código para execução --trecho com códigos para execução, onde variáveis podem ser alocadas em tempo de execução, desde que sejam referenciadas por um tipo de acesso referente ao tipo alocado end Main; 'Capacidade de Escrita' A capacidade de escrita de Ada é reduzida quanto comparada as expressões bastantes compactas de C. Estas formas maiores são consequência da visão de que Ada deve ter uma boa manutebilidade, e por isso deve ter declarações de tipos, variáveis, procedimentos funções e pacotes bem detalhada. Numa comparação de declaração de variáveis e impressão seria o seguinte: //Em C int i = 0; float f = 0; char string13 = "vetor string"; printf("%d %f %s", &i, &f, string); --Em Ada i : Integer := 0; f : Float := 0.0; string : String(1..13) := "vetor string"; Put(Integer'Image(i)); Put(Float'Image(f)); Put(string.all); --Métodos Integer'Image e Float'Image transformam o conteúdo de uma variável, no caso i e f, para String --Só é obrigatório o uso de .all em strings quando são utilizados tipos de acesso, quando não, uso é opcional e não acarreta em prejuízos ; Apesar de perder no ponto vista de algumas expressões, Ada consegue fazer declações de tipos tão ou mais poderosas que Structs em C, se tornando uma ótima opção para soluções diferenciadas. Exemplos dessa capacidade é a declaração de tipos e subtipos. procedure DayTest is --Tipos de dia e dia de trabalho type Day is (Mon, Tue, Wed, Thu, Fri, Sat, Sun); subtype WorkDay is Day range Mon..Fri; --Variável do tipo dia com conteúdo Monday days : Day := Mon; begin put(Boolean'Image(days in WorkDay)); -- Imprimi se o conteúdo da variável days faz parte de dias de trabalho, como resultado é booleano é necessário extrair a Imagem dele, ou seja, transformalo em string para ser impresso 'Documentação' A documentação de Ada é bem formalizada e ela tem sua gramática BNF, acessível em http://cui.unige.ch/isi/bnf/Ada95/BNFindex.html 'Sintaxe' 'Palavras reservadas' As palavras reservadas usadas em ADA 95 são: abort else pragma while abs elsif private whith abstract end procedure xor entry exception protected accept access exit raise aliased for range all function record and generic rem array goto renames at if requeue begin in return body is reverse case limited select constant loop separate declare mod subtype delay new tagged delta not task digits null terminate do of then declare or type delay others until delta out use digits package when 'Operadores' 'Lista de operadores em ordem de precedência' Maior ** abs not * / rem mod + - (unários) + - & (binários) = /= < > <= >= and or xor Menor 'Tipos Primitivos' Tipo de Enumeração Tipo que atribui a cada a um a si uma sequência de termos com valores do tipo e de posição. Exemplos: type Day is (Mon, Tue, Wed, Thu, Fri, Sat, Sun); type Suit is (Clubs, Diamonds, Hearts, Spades); type Gender is (M, F); Tipo Caracter Tipo caracter é predefinido como um caracter que tem valor previsto pelas 256 code positions da Row 00 (Latin-1) do ISO 10646 Basic Multilingual Plane (BMP). Exemplo: type Roman_Digit is ('I', 'V', 'X', 'L', 'C', 'D', 'M'); Tipo Booleano Tipo que pode somente apresentar os valores VERDADEIRO e FALSO. A relação definiida diz que FALSO < VERDADEIRO. Tipo Inteiro Tipo que define um inteiro com sinal ou o módulo de um inteiro (corresponde à um inteiro sem sinal) Exemplo: type Page_Num is range 1 .. 2_000; Tipos Reais Tipo que providencia uma aproximação de números reis com limites relativos aos erros do tipo ponto flutuante e limites absolutos em relação aos tipos de ponto fixo. Tipo Ponto Flutuante Tipo ponto flutuante representa números com várias casas decimais. Seu erro é definido de acordo com a precisão relativa dada por um número mínimo de casas decimais significantes. Tipo de Ponto Fixo Tipo é um número de ponto fixo comum ou um ponto fixo decimal. Os limites dos erros são especificados como um valor absoluto chamdo delta de um tipo de ponto fixo. Exemplo: type Volt is delta 0.125 range 0.0 .. 255.0; Referência: http://www.adahome.com/rm95/ 'Tipos Derivados' Tipo'' Array'' Um objeto array é objeto composto por objetos que são todos do mesmo subtipo. O valor de um array é consiste do valor de seus componentes. Exemplo: type Table is array(1 .. 10) of Integer; type Schedule is array(Day) of Boolean; Tipo'' String'' Tipo especial de array ''que é composto somente de caracteres. ''Exemplo: Question : constant String := "Isso eh uma string?"; Tipo ''Record'' Um objeto do tipo record é composto por outros objeto que consistem de componentes nomeados. O valor de um objeto'' record é tirado do valor de seus componenter. ''Exemplo: Declaração type Date is record Day : Integer range 1 .. 31; Month : Month_Name; Year : Integer range 0 .. 4000; end record; Referência: adahome.com/rm95/ 'Tipos de Acesso ' O valor de um tipo de acesso disponibiliza acesso indireto à um objeto ou subprograma. Dependendo do seu tipo, o valor de acesso pode designar subprogramas, objetos criados por alocadores ou objetos com alias genéricos de um tipo apropriado. Exemplos: type Peripheral_Ref is access Peripheral; --Tipo de acesso de um periférico --Exemplo de tipos de acesso, servindo como ponteiro para um tipo Nó, --essencial na criação de árvores type No; type PonteiroNo is access No; type No is record pai : PonteiroNo; filhoEsquerdo : PonteiroNo; filhoDireito : PonteiroNo; end No; --Para acessar o conteudo de um nó acessável por 'a', de tipo PonteiroNo, --basta acessar como no nó comum a.pai, a.filhoEsquerdo, a.filhoDireito. --Para instanciar um No e gerenciá-lo a partir de seu PonteiroNo é --necessário o seguinte: P : PonteiroNo; A : aliased No; P := A'Access; --Ou P := new No; ; Referência: adahome.com/rm95/rm9x-03-10.html Tipos de Tarefas Em Ada é possível fazer programação concorrente, o que abre grandes possíbilidades de uso, e por isso é tão utilizada em sistemas de controle de tráfego aéreo, onde é necessário avaliar a horário e quantidade de chegada e saída de aeronaves, tempo de estacionamento e manobra, quantidade de combustível de aviões em voo e mais fatores, para assim ordenar as aeronaves para pouso e decolagem. Outro exemplo possível seria em um sistema AntiBurn de processadores de um computador: procedure AntiBurn is task body Check_CPU_Temperature is .... --tarefa fica verificando a temperatura do CPU end Check_CPU_Temperature; task body Manage_Fan_Speed is .... --tarefa controla velocidade de um FAN end Manage_Fan_Speed; begin null; --Procedimento aguarda até que ambas as tarefas sejam terminadas end AntiBurn; 'Construtores' Pode-se instanciar um dos tipos primitivos ou derivados declarando-os da seguinte maneira: variável : tipo; Exemplos com vários tipos: quantidade : Integer; arquivo : Text_IO.File_Type; tempo : Calendar.Time; litros : Float; Para instanciar um tipo e iniciá-lo com um valor diferente do padrão, basta adicionar ':=' (sem as aspas) e o valor desejado: quantidade : Integer := 4; tempo : Time := Calendar.Clock; litros : Float := 2,5; Alguns tipos não permitem a instanciação do valor durante a parte de declaração de variáveis, que é separada do corpo de execução do programa. O arquivo é um desses casos, em que seria necessário fazer o seguinte: --Inclusão de pacotes with Text_IO; use Text_IO; --Início do programa procedure Main is --Declaração de variáveis, tipos, procedimentos e funções encapsuladas --pelo programa principal arquivo : Text_IO.File_Type; --Declaração do funcionamento do programa principal begin --Criação de um arquivo de texto para escrita, caso quisesse um arquivo --para leitura,seria necessário alterar Text_IO.Out_File para Text_IO.In_File Create(File => arquivo, Mode => Text_IO.Out_File, Name => "arquivo.txt"); end Main; Além dos construtores já vistos, os tipos podem ser instanciados a partir da palavra reservada 'new', que é utilizada quando são usados tipos de acessos (espécie de ponteiros). Abaixo um exemplo de como se usar um tipo de acesso: with Text_IO; use Text_IO; procedure Main is string : access String; begin string := new String(1..20); --String de 20 posições Text_IO.Put_Line(string.all); -- .all serve para acessar todo o conteúdo -- do tipo acesso String end Main; Tipos e Registros Métodos de classes e conteúdo de structs/classes são acessados de formas diferentes. Java não há distinção clara entre o que é uma variável e um método dentro de uma classe, como na seguinte classe telefone: class telefone { String telefone; --variável é declarada no corpo da classe String get_telefone (void){ return this.telefone; --método retorna a variável da classe }; }; em que podemos acessar a variável telefone tanto por telefone.telefone quanto telefone.get_telefone. Em Ada acontece o seguinte: package tel is --pacote encapsula tipo telefone e métodos que fazem seu uso procedure Put (t: telefone); --método para retornar valor de número type telefone is tagged --declaração do tipo record numero: String (1..10); end record; end tel; em que podemos acessar a variável telefone através de telefone.numero, assim como Structs em C, e o método da classe/tipo pode ser acessada por telefone'Put, assim distinguindo acesso de valores com . e métodos com ' . Alocação dinâmica de memória Ada, assim como C, permite que seja alocadada memória em tempo de execução, de forma bem semelhante ao C, porém com palavras reservadas que se aproximam mais da criação de objetos em Java. procedure Main is --Alocando memória para um caracter pointerChar : access Character; begin pointerChar := New Character; pointerChar.all := ASCII.NUL; --Memória alocada para o caractere na heap é liberada no fim da execução end Main; --Para ter um controle ainda maior da alocação e liberação de memória é possível fazer uso dao pacote Ada.Unchecked_deallocation; with Ada.Unchecked_Deallocation; procedure Main is type Character_Ptr is access Character; procedure Free is new Ada.Unchecked_Deallocation(Character, Character_Ptr); pointerChar : Character_Ptr; begin pointerChar := New Character; pointerChar.all := ASCII.NUL; Free(pointerChar) end Main; 'Pacotes' Pacotes são unidades de programa que permitem a especificação de entidades logicamente relacionadas. Tipicamente um pacote apresenta uma declaração de um tipo (frequentemente um tipo privado ou extensão privada) junto com a declaração de subprogramas primitivos de um tipo, os quais podem ser chamados de fora do pacote, enquanto o trabalho interno se mantém escondido do usuário. Podemos comparar pacotes com as bibliotecas em C ou como definição de classes em Java. Assim como os pacotes as bibliotecas abstraem do cliente grande parte da implementação de suas funções e são unidades com definições lógicas bem claras de seus serviços. Um pacote geralmente é formado de duas partes: a especificação e o corpo. Todo pacote apresenta uma especificação, mas nem todos tem um corpo. A declaração do pacote precisa de um corpo se contém algum intem que não foi implementado na declaração. Esses itens serão implementados depois no corpo do pacote. Em contraste com as entidades declaradas na parte visível do pacote as entidades declaradas dentro do corpo do pacote são vistas somente dentro do próprio corpo do pacote. Por isso um pacote com corpo pode construir um grupo de subprogramas relacionados nos quais as operações lógicas são isolados das entidades internas. Exemplo de Declaração de Pacote (Abstract Data Type - ADT): package Rational_Numbers is type Rational isrecord Numerator : Integer; Denominator : Positive; end record; function "="(X,Y : Rational) return Boolean; function "/" (X,Y : Integer) return Rational; function "+" (X,Y : Rational) return Rational; function "-" (X,Y : Rational) return Rational; function "*" (X,Y : Rational) return Rational; function "/" (X,Y : Rational) return Rational; end Rational_Numbers; Exemplo de Corpo do Pacote (Abstract State Machine - ASM): package body Rational_Numbers is procedure Same_Denominator (X,Y : in out Rational) is begin -- Leva X e Y à um mesmo denominador end Same_Denominator; function "="(X,Y : Rational) return Boolean is U : Rational := X; V : Rational := Y; begin Same_Denominator (U,V); return U.Numerator = V.end "="; end '='; function "/" (X,Y : Integer) return Rational is begin if Y > 0 then return (Numerator => X, Denominator => Y); else return (Numerator => -X, Denominator => -Y); end if; end "/"; function "+" (X,Y : Rational) return Rational is ... end "+"; function "-" (X,Y : Rational) return Rational is ... end "-"; function "*" (X,Y : Rational) return Rational is ... end "*"; function "/" (X,Y : Rational) return Rational is ... end "/"; end Rational_Numbers; Referência: adaic.org/resources/add_content/standards/05rm/html/RM-7.html 'Estruturas de Controle' Ada contém uma série de estruturas de controle. Além dos tradicionais If, Else, For e While de C, temos combinações deles com GoTo, sendo possível pular para Labels dentro ou fora de um loop. Abaixo exemplos de estruturas de controle: case X is when 1 => Walk_The_Dog; when others => Self_Destruct; end case; if condition then statement; elsif condition then other statement; else another statement; end if; Until_Loop: --label para GoTo loop --palavra reservada para loops X:= Calculate_Something; exit Until_Loop when X>5; --condição de saída do Loop end loop Until_Loop; Array_Loop: for I in X'Range loop X(I+X'First):=Get_Next_Element; --X é um array, com índices num intervalo 1..X'Range . Uso de X'First é essencial, ao menos com uso de strings, pois acesso das posições é dado pelo endereço inicial + offset end loop Array_Loop; --Loops aninhados X_Loop: while x < 1000000 loop Y_Loop: while y < 1000000 loop put(Integer'Image(y+x)); if condicaoParada = TRUE then --Comparando se a condição de parada é verdadeira, sendo, a saída é do Loop X, ou seja, pula fora tanto do loop Y quanto do X end loop X_Loop; end if; end loop Y_Loop; y:=0; end loop X_Loop; 'Referências' Ada Core. Ada Comparision Chart. Disponível em: http://www.adacore.com/adaanswers/about/ada-comparison-chart/ Ada Core. Ada 2012. Disponível em: http://www.ada2012.org/ WikiBooks. Wiki Ada Programming. Disponível em: http://en.wikibooks.org/wiki/Ada_Programming REEDY, Christopher.' Ada Resources: Chapter 11 - Memory Allocation'. Disponível em: http://faculty.cs.wwu.edu/reedyc/AdaResources/bookhtml/ch11.htm BOTTON, David. Ada Power. Disponível em: http://www.adapower.com/ GUYOT, Jacques; ESTIER, Thibault; CRAUSAZ, Pascal. BNF Ada 95. Disponível em: http://cui.unige.ch/isi/bnf/Ada95/BNFindex.html OKIE, Edward. Procedural Analysis and Design: Subtypes. Disponível em: http://www.radford.edu/~nokie/classes/320/subtypes.html